package cn.com.transfer.listener;

import cn.com.transfer.services.MsgHandlerService;
import cn.com.transfer.utils.IcbcInfo;
import cn.com.transfer.utils.IcbcNative;
import flexjson.JSONDeserializer;
import org.apache.commons.lang.StringUtils;
import org.nutz.ioc.Ioc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.*;

import static cn.com.transfer.utils.IcbcInfo.end;
import static cn.com.transfer.utils.IcbcInfo.start;

/**
 * 启动定时器 签到 签退 对账
 */
public class IcbcServer {
    private Logger logger = LoggerFactory.getLogger(IcbcServer.class);
    private Timer timer1, timer2, timer3;
    private Ioc ioc;
    private Long dayTime = 24 * 60 * 60 * 1000L;

    public void start() {
        //复制resources目录dll文件到tomcat\bin目录
//        copyDll();
        //启动定时任务
        startTimer();
    }

    public void stop() {
        try {
            timer1.cancel();
        } catch (Exception e) {
        }
        try {
            timer2.cancel();
        } catch (Exception e) {
        }
        try {
            timer3.cancel();
        } catch (Exception e) {
        }
        try {
            IcbcNative.dispose();
        } catch (Exception e) {
        }
    }

    private void copyDll() {
        String name = "hsdes.dll";
        String dir = System.getProperty("catalina.home") + "\\bin";
        File out = new File(dir + File.separator + name);
        File in = new File(this.getClass().getClassLoader().getResource(name).getPath());
        FileChannel ic = null, oc = null;
        try {
            ic = new FileInputStream(in).getChannel();
            oc = new FileOutputStream(out).getChannel();
            ic.transferTo(0, ic.size(), oc);
        } catch (Exception e) {
            logger.error("error in copy dll", e);
        } finally {
            try {
                ic.close();
            } catch (IOException e) {
            }
            try {
                oc.close();
            } catch (IOException e) {
            }
        }
    }

    private void startTimer() {
        try {
            if (StringUtils.isBlank(start) && !start.matches("(2[0-4]|[0-1]\\d)([0-5]\\d){2}"))
                start = "060000";
            if (StringUtils.isBlank(end) && !end.matches("(2[0-4]|[0-1]\\d)([0-5]\\d){2}"))
                end = "203000";
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, Integer.valueOf(start.substring(0, 2)));
            calendar.set(Calendar.MINUTE, Integer.valueOf(start.substring(2, 4)));
            calendar.set(Calendar.SECOND, Integer.valueOf(start.substring(4, 6)));
            Date start = calendar.getTime();

            calendar.set(Calendar.HOUR_OF_DAY, Integer.valueOf(end.substring(0, 2)));
            calendar.set(Calendar.MINUTE, Integer.valueOf(end.substring(2, 4)));
            calendar.set(Calendar.SECOND, Integer.valueOf(end.substring(4, 6)));
            Date end = calendar.getTime();

            if (new Date().after(end)) {
                start = addDay(start, 1);
                end = addDay(end, 1);
            }
            //签到
            signIn(start);
            //签退
            signOut(end);
            //对账
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            calendar.set(Calendar.HOUR_OF_DAY, 5);
            calendar.set(Calendar.MINUTE, 0);
            Date balance = calendar.getTime();
            accCheck(balance);

        } catch (Exception e) {
            logger.error("error in startTimerForIcbc", e);
        }
    }

    /**
     * 签到
     *
     * @param start
     */
    private void signIn(Date start) {
        timer1 = new Timer();
        timer1.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    MsgHandlerService signIn = ioc.get(MsgHandlerService.class, "signIn");
                    boolean bool = true;
                    while (bool) {
                        String handler = signIn.handler(new HashMap());
                        Map map = new JSONDeserializer<Map>().deserialize(handler);
                        if ((Boolean) map.get("success") != true) {
                            logger.error("签到失败");
                            Thread.sleep(10 * 60 * 1000);
                        } else {
                            bool = false;
                        }
                    }
                } catch (Exception e) {
                    logger.error("error in timer1.sign_in", e);
                }
            }
        }, start, dayTime);
        logger.info("start timer at {} for SIGN_IN", IcbcInfo.start);
    }

    /**
     * 签退
     *
     * @param end
     */
    private void signOut(Date end) {
        timer2 = new Timer();
        timer2.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    MsgHandlerService signOut = ioc.get(MsgHandlerService.class, "signOut");
                    String handler = signOut.handler(new HashMap());
                } catch (Exception e) {
                    logger.error("error in timer2.sign_out", e);
                }
            }
        }, end, dayTime);
        logger.info("start timer at {} for SIGN_OUT", IcbcInfo.end);
    }

    /**
     * 对账
     *
     * @param balance
     */
    private void accCheck(Date balance) {
        timer3 = new Timer();
        timer3.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    MsgHandlerService signOut = ioc.get(MsgHandlerService.class, "accCheck");
                    String handler = signOut.handler(new HashMap());
                } catch (Exception e) {
                    logger.error("error in timer3.check_acc", e);
                }
            }
        }, balance, dayTime);
        logger.info("start timer at {} for checkAcc", balance.toString());
    }

    private Date addDay(Date date, int i) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, i);
        return calendar.getTime();
    }
}
